import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import GUI.GUIManager;


public class MainClass
{
	private static int numOfChars = 68;
	private static char[] indices = { 'A', 'Z', 'a', 'z', '0', '9', '+', '!', '@', '#', '$', '='};
	
	public static Vector<Component> comps;
	public static Vector<Component> monitored;
	public static Vector<Test>		tests;
	public static Component OStar = new Component(-1, -1);
	public static Component chosenComponent;
	public static int timesToRun = 70;
	public static Vector<Vector<Double>> Cds;
	
	/**
	 * builds a vector of components, each component gets a char 
	 * between A to Z or between a to z or between 0 to 9 or one of  '+', '!', '@', '#', '$', '='
	 * @return the above vector
	 */
	public static Vector<Component> createComps() 
	{
		Vector<Component> result = new Vector<Component>();
		Component c;
		int count = 0;
		for (char i = indices[0]; i <= indices[1]; i++) 
		{
			c = new Component(count, 1);
			c.setC(i);
			result.add(c);
			count++;
		}
		for (char i = indices[2]; i <= indices[3]; i++) 
		{
			c = new Component(count, 1);
			c.setC(i);
			result.add(c);
			count++;
		}
		for (char i = indices[4]; i <= indices[5]; i++) 
		{
			c = new Component(count, 1);
			c.setC(i);
			result.add(c);
			count++;
		}
		for (int i = 6; i < indices.length; i++) 
		{
			c = new Component(count, 1);
			c.setC(indices[i]);
			result.add(c);
			count++;
		}
		return result;
	}
	
	/**
	 * main function of the project:
	 * @param args
	 */
	public static void main(String[] args)
	{
		try
		{

			comps = createComps();
			OurInputClass.BuildRandomGraphFromComps(comps);
			OurInputClass.BuildCovrageMatrix();
			OurInputClass.BuildTests();
			monitored = OurInputClass.leaves;
			CoverageMatrix cov = OurInputClass.covMat;
			
			/**
			 * starting to run tiger - assuming the Ith component is at fault:
			 * graph's color: red
			 */
			Tiger tiger;
			
			Vector<Double> chosenCompCd = new Vector<Double>();
			chosenComponent = OurInputClass.tree.elementAt((int)(Math.random()*OurInputClass.tree.size()));
			chosenComponent.setHealth(0);
			tests = OurInputClass.tests;
			
			tiger = new Tiger(comps, cov, monitored, tests);
			List<Pair<Component, Double>> R;
			for (int j = 0; j < timesToRun; j++) 
			{
				tiger.Run();
				R = tiger.getR();
				chosenCompCd.add(calcCd(R, chosenComponent));
			}
			
			chosenComponent.setHealth(1);
			/**
			 * starting to run Lion - will show the decreasing at the largest ambiguity group's size:
			 * graph's color: blue
			 */
			OurInputClass.restartInput(); // restart all the input to new input.
			
			comps = createComps();
			OurInputClass.BuildRandomGraphFromComps(comps);
			OurInputClass.BuildCovrageMatrix();
			monitored = OurInputClass.leaves;
			cov = OurInputClass.covMat;
			
			Vector<Integer> largestAmbiguityGroupSizes = new Vector<Integer>();
			for (int j = 0; j < timesToRun; j++) 
			{
				cov = LionAlgorithm.Lion(cov, monitored, comps);
				largestAmbiguityGroupSizes.add(LionAlgorithm.largestAmbiguityGroupSize);
			}
			
			Vector<Double> lionGraph = createLionGraph(largestAmbiguityGroupSizes);
			
			GUIManager mainWin = new GUIManager();
			mainWin.addSpline(chosenCompCd, Color.red);
			mainWin.addSpline(lionGraph, Color.blue);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * normalize the size of each ambiguity group's size between 0 to 1
	 * @param largestAmbiguityGroupSizes  ambiguity group's size in each running of lion
	 * @return
	 */
	private static Vector<Double> createLionGraph(Vector<Integer> largestAmbiguityGroupSizes) 
	{
		Vector<Double> res = new Vector<Double>();
		for (int i = 0; i < largestAmbiguityGroupSizes.size(); i++) 
		{
			res.add((double)(largestAmbiguityGroupSizes.elementAt(i))/largestAmbiguityGroupSizes.elementAt(0)*1.0);
		}
		return res;
	}

	private static Double calcCd(List<Pair<Component, Double>> r, Component comp) 
	{
		int Mf = 1;
		int f  =-1;
		int count = 0;
		for (Iterator iterator = r.iterator(); iterator.hasNext();) 
		{
			Pair<Component, Double> pair = (Pair<Component, Double>) iterator.next();
			if(pair.first.getId() == comp.getId())
			{
				f = count;
			}
			count ++;
		}
		return (f-Mf)/((double)(r.size() - Mf));
	}
}
